﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ServiceModel;
using Cherry.Agile.Framework;
using System.Security.Permissions;
using System.Runtime.Remoting.Lifetime;
namespace Cherry.Agile.ServiceModel.Runtime
{
    public class RemoteServiceRunner : MarshalByRefObject, IServiceRunner
    {
        [SecurityPermissionAttribute(SecurityAction.Demand,
                             Flags = SecurityPermissionFlag.Infrastructure)]
        public override Object InitializeLifetimeService()
        {
            //ILease lease = (ILease)base.InitializeLifetimeService();
            //if (lease.CurrentState == LeaseState.Initial)
            //{
            //    lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
            //    lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
            //    lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
            //}
            //return lease;
            return null;
        }

        List<IService> service = new List<IService>();
        object _sync = new object();
        ServicePackage _package;
        public RemoteServiceRunner()
        {

        }

        public RemoteServiceRunner(ServicePackage package)
        {
            _package = package;
            Load(package);
        }

        public void Load(ServicePackage package)
        {
            var address = Config.RempServiceModelSection.Current.Service.Address;
            if (string.IsNullOrEmpty(address))
                package.BaseAddress = address;

            lock (_sync)
            {
                service = RuntimeUnity.GetService(package);    
            }
            
        }

        public void Run(IEventListener listener, IServiceFilter filter)
        {
            lock (_sync)
            {
                service.Where(c => c.RunState != RunState.Runnable && filter.Pass(c)).ForEach(
                    r =>
                    {
                        try
                        {
                            r.Run();
                            listener.Started(r.Info);
                        }
                        catch (Exception ex)
                        {
                            listener.Error(r.Info, ex);
                        }
                    });
            }
        }

        public void Stop(IEventListener listener, IServiceFilter filter)
        {
            lock (_sync)
            {
                service.Where(c => filter.Pass(c)).ForEach(
                    r =>
                    {
                        try
                        {
                            r.Stop();
                            listener.Stoped(r.Info);
                        }
                        catch (Exception ex)
                        {
                            listener.Error(r.Info, ex);
                        }
                    });
            }
        } 

        public IEnumerable<ServiceInfo> Info(IServiceFilter filter)
        {
            return service.Where(c => filter.Pass(c))
                .Select(s => new ServiceInfo() { FullName = s.Info.FullName, State = s.RunState }).ToArray();
        }

        public IEnumerable<ServiceInfo> GetServicesInfo() {
            return service.Select(c=>c.Info);
        }
    }
}
